home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC]
/
NeXTSTEP 3.3 Dev Intel.iso
/
usr
/
sybase
/
sample
/
dblibrary
/
twophase.c
< prev
Wrap
C/C++ Source or Header
|
1993-04-22
|
6KB
|
235 lines
/*
** twophase.c
**
** Demo of Two-Phase Commit Service
**
** This example uses the two-phase commit service
** to perform a simultaneous update on two servers.
** In this example, one of the servers participating
** in the distributed transaction also functions as
** the commit service.
**
** In this particular example, the same update is
** performed on both servers. You can, however, use
** the commit server to perform completely different
** updates on each server.
**
*/
#include <stdio.h>
#include <sybfront.h>
#include <sybdb.h>
int err_handler();
int msg_handler();
char cmdbuf[256];
char xact_string[128];
main()
{
DBPROCESS *dbproc_server1;
DBPROCESS *dbproc_server2;
DBPROCESS *dbproc_commit;
LOGINREC *login;
int commid;
RETCODE ret_server1;
RETCODE ret_server2;
/* Initialize DB-Library. */
if (dbinit() == FAIL)
exit(ERREXIT);
dberrhandle(err_handler);
dbmsghandle(msg_handler);
printf("Demo of Two Phase Commit\n");
/* Open connections with the servers and the commit service. */
login = dblogin();
DBSETLPWD(login, "server_password");
DBSETLAPP(login, "twophase");
dbproc_server1 = dbopen (login, "SERVICE");
dbproc_server2 = dbopen (login, "PRACTICE");
dbproc_commit = open_commit (login, "SERVICE");
if (dbproc_server1 == NULL ||
dbproc_server2 == NULL ||
dbproc_commit == NULL)
{
printf (" Connections failed!\n");
exit (ERREXIT);
}
/* Use the "pubs" database. */
sprintf(cmdbuf, "use pubs");
dbcmd(dbproc_server1, cmdbuf);
dbsqlexec(dbproc_server1);
dbcmd(dbproc_server2, cmdbuf);
dbsqlexec(dbproc_server2);
/* Start the distributed transaction on the commit service. */
commid = start_xact(dbproc_commit, "demo", "test", 2);
/* Build the transaction name. */
build_xact_string ("test", "SERVICE", commid, xact_string);
/* Build the first command buffer. */
sprintf(cmdbuf, "BEGIN TRANSACTION %s", xact_string);
/* Begin the transactions on the different servers. */
dbcmd(dbproc_server1, cmdbuf);
dbsqlexec(dbproc_server1);
dbcmd(dbproc_server2, cmdbuf);
dbsqlexec(dbproc_server2);
/* Do various updates. */
sprintf(cmdbuf, " update titles set price = $1.50 where");
strcat(cmdbuf, " title_id = 'BU1032'");
dbcmd(dbproc_server1, cmdbuf);
ret_server1 = dbsqlexec(dbproc_server1);
dbcmd(dbproc_server2, cmdbuf);
ret_server2 =dbsqlexec(dbproc_server2);
if (ret_server1 == FAIL || ret_server2 == FAIL)
{
/* Some part of the transaction failed. */
printf(" Transaction aborted -- dbsqlexec failed\n");
abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
}
/* Find out if all servers can commit the transaction. */
sprintf(cmdbuf, "PREPARE TRANSACTION");
dbcmd(dbproc_server1, cmdbuf);
dbcmd(dbproc_server2, cmdbuf);
ret_server1 = dbsqlexec(dbproc_server1);
ret_server2 = dbsqlexec(dbproc_server2);
if (ret_server1 == FAIL || ret_server2 == FAIL)
{
/* One or both of the servers failed to prepare. */
printf(" Transaction aborted -- PREPARE failed\n");
abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
}
/* Commit the transaction. */
if (commit_xact(dbproc_commit, commid) == FAIL)
{
/* The commit server failed to record the commit. */
printf( " Transaction aborted -- commit_xact failed\n");
abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
exit(ERREXIT);
}
/* The transaction has successfully committed. Inform the servers. */
sprintf(cmdbuf, "COMMIT TRANSACTION");
dbcmd(dbproc_server1, cmdbuf);
if (dbsqlexec(dbproc_server1) != FAIL)
remove_xact(dbproc_commit, commid, 1);
dbcmd(dbproc_server2, cmdbuf);
if (dbsqlexec(dbproc_server2) != FAIL)
remove_xact(dbproc_commit, commid, 1);
/* Close the connection to the commit server. */
close_commit(dbproc_commit);
printf( "We made it!\n");
dbexit();
exit(STDEXIT);
}
/* Function to abort the distributed transaction. */
abortall( dbproc_server1, dbproc_server2, dbproc_commit, commid )
DBPROCESS *dbproc_server1;
DBPROCESS *dbproc_server2;
DBPROCESS *dbproc_commit;
int commid;
{
/* Some part of the transaction failed. */
/* Inform the commit server of the failure. */
abort_xact(dbproc_commit, commid);
/* Roll back the transactions on the different servers. */
sprintf(cmdbuf, "ROLLBACK TRANSACTION");
dbcmd(dbproc_server1, cmdbuf);
if (dbsqlexec(dbproc_server1) != FAIL)
remove_xact(dbproc_commit, commid, 1);
dbcmd(dbproc_server2, cmdbuf);
if (dbsqlexec(dbproc_server2) != FAIL)
remove_xact(dbproc_commit, commid, 1);
dbexit();
exit(ERREXIT);
}
/* Message and error handling functions. */
int msg_handler(dbproc, msgno, msgstate, severity, msgtext,
servername, procname, line)
DBPROCESS *dbproc;
DBINT msgno;
int msgstate;
int severity;
char *msgtext;
char *servername;
char *procname;
DBUSMALLINT line;
{
/* Msg 5701 is just a USE DATABASE message, so skip it. */
if (msgno == 5701)
return (0);
/* Print any severity 0 message as is, without extra stuff. */
if (severity == 0)
{
printf ("%s\n",msgtext);
return (0);
}
printf ("Msg %ld, Level %d, State %d\n",
msgno, severity, msgstate);
if (strlen(servername) > 0)
printf ("Server '%s', ", servername);
if (strlen(procname) > 0)
printf ("Procedure '%s', ", procname);
if (line > 0)
printf ("Line %d", line);
printf("\n\t%s\n", msgtext);
if (severity >= 16)
{
printf("Program Terminated! Fatal SQL Server error.\n");
exit(ERREXIT);
}
return (0);
}
int err_handler(dbproc, severity, dberr, oserr, dberrstr, oserrstr)
DBPROCESS *dbproc;
int severity;
int dberr;
int oserr;
char *dberrstr;
char *oserrstr;
{
if ((dbproc == NULL) || (DBDEAD(dbproc)))
return (INT_EXIT);
else
{
printf ("DB-Library error: \n\t%s\n", dberrstr);
if (oserr != DBNOERR)
printf ("Operating system error:\n\t%s\n", oserrstr);
}
return (INT_CANCEL);
}